package com.atguigu.srb.core.service.impl;

import com.atguigu.srb.base.result.ResponseEnum;
import com.atguigu.srb.base.util.JwtUtils;
import com.atguigu.srb.base.util.SrbAssert;
import com.atguigu.srb.core.pojo.entity.*;
import com.atguigu.srb.core.mapper.BorrowInfoMapper;
import com.atguigu.srb.core.pojo.entity.vo.*;
import com.atguigu.srb.core.service.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.jws.Oneway;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 借款信息表 服务实现类
 * </p>
 *
 * @author Atguigu
 * @since 2024-10-11
 */
@Service
public class BorrowInfoServiceImpl extends ServiceImpl<BorrowInfoMapper, BorrowInfo> implements BorrowInfoService {

    @Resource
    UserInfoService userInfoService;
    @Resource
    IntegralGradeService integralGradeService;
    @Resource
    DictService dictService;
    @Resource
    BorrowerService borrowerService;

    @Resource
    LendService lendService;

    @Override
    public void saveApply(BorrowInfo borrowInfo, String token) {
        UserInfo userInfo = userInfoService.checkUserStatus(token);
        Long userId = userInfo.getId();
        //3、校验用户是否有待审核/还款中的借款
            //3.1 borrow_info表中 如果当前用户有状态为待审核的借款信息  不能再次借款
        int count = this.count(Wrappers.lambdaQuery(BorrowInfo.class)
                .eq(BorrowInfo::getUserId,userId)
                .eq(BorrowInfo::getStatus,1));
        SrbAssert.AssertNotTrue(count!=0,ResponseEnum.USER_BORROW_INFO_EXISTS_ERROR);
            //3.2 lend表中 如果当前用户有状态为待发布或者募资中或者更还款中的标的  不能再次借款
                /*
                    CHECK(0, "待发布"),
                    INVEST_RUN(1, "募资中"),
                    PAY_RUN(2, "还款中"),
                    PAY_OK(3, "已结清"),
                    FINISH(4, "结标"),
                    CANCEL(-1, "已撤标"),
                 */
        count = lendService.count(Wrappers.lambdaQuery(Lend.class)
                .eq(Lend::getUserId,userId)
                .in(Lend::getStatus,0,1,2));
        SrbAssert.AssertNotTrue(count!=0,ResponseEnum.USER_BORROW_INFO_EXISTS_ERROR);
        //4、验证用户借款金额是否超过自己的借款额度
        //查询借款额度
        BigDecimal amount = integralGradeService.getBorrowAmountByUserId(token);
        SrbAssert.AssertNotTrue(borrowInfo.getAmount().doubleValue()>amount.doubleValue()
                ,ResponseEnum.USER_AMOUNT_LESS_ERROR);


        //5、校验没问题后，保存借款申请到数据库中
        borrowInfo.setUserId(userId);
        borrowInfo.setStatus(1);//审核中
        this.save(borrowInfo);
    }

    @Override
    public void getMyBorrows(Page<BorrowInfo> page, String token) {
        Long userId = JwtUtils.getUserId(token);
        //查询数据
        this.page(page,Wrappers.lambdaQuery(BorrowInfo.class)
                .eq(BorrowInfo::getUserId,userId)
                .orderByDesc(BorrowInfo::getCreateTime));
        //完善数据：将每个BorrowInfo的数据字典的name值设置到params集合中
        List<BorrowInfo> borrowInfos = page.getRecords();
        borrowInfos.forEach(borrowInfo -> {
            Integer status = borrowInfo.getStatus();
            Integer moneyUse = borrowInfo.getMoneyUse();
            Integer returnMethod = borrowInfo.getReturnMethod();
            Map<String,String> params =new HashMap<>();
            String state = getStatusDesc(status);

            params.put("status",state);
            params.put("moneyUse",dictService.
                    getDictNameByDictCodeAndValue("moneyUse",moneyUse));
            params.put("returnMethod",dictService.
                    getDictNameByDictCodeAndValue("returnMethod",returnMethod));
            borrowInfo.setParams(params);
        });
    }

    private static String getStatusDesc(Integer status) {
        String state="";
        switch (status){
            case 0:
                state = "未提交";
                break;
            case 1:
                state = "审核中";
                break;
            case 2:
                state = "审核通过";
                break;
            case -2:
                state = "已撤销";
                break;
            default:
                state = "审核不通过";
                break;

        }
        return state;
    }

    @Override
    public Page<BorrowInfoVO> getBorrowInfoVOs(BorrowInfoSearchVO borrowInfoSearchVO, Integer pageNum, Integer pageSize) {

        try {
            //1、条件分页查询借款列表
            LambdaQueryWrapper<BorrowInfo> wrapper = Wrappers.lambdaQuery(BorrowInfo.class);
            //封装查询条件
            //1.1 模糊查询的关键词
//        String keyword = borrowInfoSearchVO.getKeyword();
            //因为 用户姓名和手机号码存在userInfo表中， 需要根据这些条件筛选数据，必须多表联查
//        if(StringUtils.isNotEmpty(keyword)){
//            wrapper.like()
//        }
            //1.2 借款记录状态
            Integer status = borrowInfoSearchVO.getStatus();
            if(status!=null){
                wrapper.eq(BorrowInfo::getStatus , status);
            }
            //1.3 资金用途
            Integer moneyUse = borrowInfoSearchVO.getMoneyUse();
            if(moneyUse!=null){
                wrapper.eq(BorrowInfo::getMoneyUse , moneyUse);
            }
            //1.4 还款方式
            Integer returnMethod = borrowInfoSearchVO.getReturnMethod();
            if(returnMethod!=null){
                wrapper.eq(BorrowInfo::getReturnMethod , returnMethod);
            }
            //1.5 借款金额区间
            BigDecimal amountStart = borrowInfoSearchVO.getAmountStart();
            BigDecimal amountEnd = borrowInfoSearchVO.getAmountEnd();
            if(amountStart!=null){
                wrapper.ge(BorrowInfo::getAmount , amountStart);
            }
            if(amountEnd!=null){
                wrapper.le(BorrowInfo::getAmount , amountEnd);
            }

            //1.5 申请时间范围
            String createTimeStart = borrowInfoSearchVO.getCreateTimeStart();
            String createTimeEnd = borrowInfoSearchVO.getCreateTimeEnd();
            //时间日期比较
            if(createTimeStart!=null){
                wrapper.ge(BorrowInfo::getCreateTime , createTimeStart);
            }
            if(createTimeEnd!=null){
                wrapper.le(BorrowInfo::getCreateTime , createTimeEnd);
            }
            //1.6 还款期数范围
            Integer periodStart = borrowInfoSearchVO.getPeriodStart();
            Integer periodEnd = borrowInfoSearchVO.getPeriodEnd();
            if(periodStart!=null){
                wrapper.ge(BorrowInfo::getPeriod , periodStart);
            }
            if(periodEnd!=null){
                wrapper.le(BorrowInfo::getPeriod , periodEnd);
            }
            wrapper.orderByDesc(BorrowInfo::getCreateTime);
            Page<BorrowInfo> borrowInfoPage = this.page(new Page<BorrowInfo>(pageNum, pageSize),
                    wrapper);
            //2、将borrowInfoPage转为BorrowInfoVO的分页对象
            Page<BorrowInfoVO> page = new Page<>();
            //拷贝页码 每页几条记录 总记录条数 等属性值    records属性 两个page对象的泛型不一样 导致拷贝失败
            BeanUtils.copyProperties(borrowInfoPage,page);
            List<BorrowInfoVO> vos = borrowInfoPage.getRecords().stream().map(borrowInfo -> {
                //将borrowInfo转为borrowInfoVo
                BorrowInfoVO borrowInfoVO = new BorrowInfoVO();
                borrowInfoVO.setId(borrowInfo.getId());
                borrowInfoVO.setAmount(borrowInfo.getAmount());
                borrowInfoVO.setCreateTime(borrowInfo.getCreateTime());
                transferBorrowIndoVO(borrowInfoVO);
                //根据userId查询会员信息
                UserInfo userInfo = userInfoService.getById(borrowInfo.getUserId());
                borrowInfoVO.setMobile(userInfo.getMobile());
                borrowInfoVO.setName(userInfo.getName());
                return borrowInfoVO;
            }).collect(Collectors.toList());

            page.setRecords(vos);

            return page;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    private void transferBorrowIndoVO(BorrowInfoVO borrowInfoVO) {
        borrowInfoVO.setPeriod(borrowInfoVO.getPeriod()+"个月");
        borrowInfoVO.setReturnMethod(dictService
                .getDictNameByDictCodeAndValue("returnMethod",
                        Integer.parseInt(borrowInfoVO.getReturnMethod())));
        borrowInfoVO.setMoneyUse(dictService
                .getDictNameByDictCodeAndValue("moneyUse",
                        Integer.parseInt(borrowInfoVO.getMoneyUse())));
        borrowInfoVO.setBorrowYearRate(borrowInfoVO.getBorrowYearRate()+"%");
        borrowInfoVO.setStatus(getStatusDesc(Integer.parseInt(borrowInfoVO.getStatus())));
    }

    @Override
    public BorrowInfoDetailVO getBorrowInfoDetail(Long id) {
        BorrowInfoDetailVO borrowInfoDetailVO = new BorrowInfoDetailVO();
        //查询借款详情
        BorrowInfoVO borrowInfoVO = baseMapper.selectBorrowInfoDetailById(id);
        this.transferBorrowIndoVO(borrowInfoVO);
        borrowInfoDetailVO.setBorrowInfoVO(borrowInfoVO);
        //查询借款人信息
        Long userId = borrowInfoVO.getUserId();
//        Borrower borrower = borrowerService.getOne(Wrappers.lambdaQuery(Borrower.class)
//                .eq(Borrower::getUserId, userId)
//                .select(Borrower::getId));
        BorrowerVO borrowerVO = borrowerService.queryBorrowerVoById(userId);
        borrowInfoDetailVO.setBorrowerVO(borrowerVO);
        return borrowInfoDetailVO;
    }

    @Override
    public Integer getStatus(String token) {
        Long userId = JwtUtils.getUserId(token);
        //排除status为-2的数据
        BorrowInfo borrowInfo = this.getOne(Wrappers.lambdaQuery(BorrowInfo.class)
                .eq(BorrowInfo::getUserId, userId)
                .ne(BorrowInfo::getStatus, -2)
                .orderByDesc(BorrowInfo::getCreateTime)
                .last("limit 1"));
        return borrowInfo==null?0:borrowInfo.getStatus();
    }

    @Override
    public void approval(BorrowInfoApprovalVO borrowInfoApprovalVO) {
        Integer status = borrowInfoApprovalVO.getStatus();
        //更新借款信息的状态
        BorrowInfo borrowInfo = new BorrowInfo();
        borrowInfo.setId(borrowInfoApprovalVO.getId());
        borrowInfo.setStatus(status);
        this.updateById(borrowInfo);
        //如果审批通过，创建新标的
        if (status==2){
            lendService.createLend(borrowInfoApprovalVO);
        }
    }


    //自定义sql实现带条件分页查询借款记录
    public Page<BorrowInfoVO> getBorrowInfoVOs2(BorrowInfoSearchVO borrowInfoSearchVO, Integer pageNum, Integer pageSize){
        Page<BorrowInfoVO> page  =  new Page<>(pageNum,pageSize);
        //1、条件分页查询借款列表
        QueryWrapper<BorrowInfo> wrapper = new QueryWrapper<BorrowInfo>();
        //封装查询条件
        //1.1 模糊查询的关键词
        String keyword = borrowInfoSearchVO.getKeyword();
        //        因为 用户姓名和手机号码存在userInfo表中， 需要根据这些条件筛选数据，必须多表联查
        if(StringUtils.isNotEmpty(keyword)){
            wrapper.and(t-> t.like("t2.name", keyword).or().like("t2.mobile",keyword));
        }
        //1.2 借款记录状态
        Integer status = borrowInfoSearchVO.getStatus();
        if(status!=null){
            wrapper.eq("t1.status" , status);
        }
        //1.3 资金用途
        Integer moneyUse = borrowInfoSearchVO.getMoneyUse();
        if(moneyUse!=null){
            wrapper.eq("t1.money_use" , moneyUse);
        }
        //1.4 还款方式
        Integer returnMethod = borrowInfoSearchVO.getReturnMethod();
        if(returnMethod!=null){
            wrapper.eq("t1.return_method" , returnMethod);
        }
        //1.5 借款金额区间
        BigDecimal amountStart = borrowInfoSearchVO.getAmountStart();
        BigDecimal amountEnd = borrowInfoSearchVO.getAmountEnd();
        if(amountStart!=null){
            wrapper.ge("t1.amount" , amountStart);
        }
        if(amountEnd!=null){
            wrapper.le("t1.amount" , amountEnd);
        }

        //1.5 申请时间范围
        String createTimeStart = borrowInfoSearchVO.getCreateTimeStart();
        String createTimeEnd = borrowInfoSearchVO.getCreateTimeEnd();
        //时间日期比较
        if(createTimeStart!=null){
            wrapper.ge("DATE(t1.create_time)", createTimeStart);
        }
        if(createTimeEnd!=null){
            wrapper.le("DATE(t1.create_time)" , createTimeEnd);
        }
        //1.6 还款期数范围
        Integer periodStart = borrowInfoSearchVO.getPeriodStart();
        Integer periodEnd = borrowInfoSearchVO.getPeriodEnd();
        if(periodStart!=null){
            wrapper.ge("t1.period" , periodStart);
        }
        if(periodEnd!=null){
            wrapper.le("t1.period", periodEnd);
        }
        //1.7 排序
        wrapper.orderByDesc("t1.create_time");

        //page对象用来携带分页条件，如果启用了mp的分页拦截器 page对象会被分页拦截器自动解析生成limit语句
        List<BorrowInfoVO> borrowInfoVOS = baseMapper.selectBorrowInfiVOs(page,wrapper);
        borrowInfoVOS.forEach(borrowInfoVO -> {
            //将borrowInfo转为borrowInfoVo
            transferBorrowIndoVO(borrowInfoVO);
        });
        //将查询的数据集合设置到分页对象中
        page.setRecords(borrowInfoVOS);
        return page;
    }

}
